package com.mxx.common.payment.ali;


import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.mxx.common.payment.*;
import com.mxx.common.exception.CommentException;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;


@Slf4j
public class DefaultAliPaymentHandler implements PaymentHandler<AliPrepaymentResponse> {


    private AliPaymentParameter paymentParameter;

    public DefaultAliPaymentHandler(AliPaymentParameter paymentParameter) {
        this.paymentParameter = paymentParameter;
    }

    protected AlipayClient createPayClient(AliPaymentParameter paymentParameter) {
        return new DefaultAlipayClient(paymentParameter.getAliGateway(), paymentParameter.getAppId(),
                paymentParameter.getRsaPrivateKey(), paymentParameter.getFormat(), paymentParameter.getCharset(),
                paymentParameter.getAliRsaPublicKey(), paymentParameter.getSignType());
    }

    @Override
    public AliPrepaymentResponse prepaymentProcess(TradeMark tradeMark) {
        if (TradeClient.APP.equals(tradeMark.getTradeClient())) {
            AlipayClient alipayClient = this.createPayClient(paymentParameter);
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

            model.setProductCode("QUICK_MSECURITY_PAY");
            model.setTimeoutExpress("15m");// 订单超时 m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）
            model.setSubject(tradeMark.getTitle()); // 商品名称
            model.setOutTradeNo(tradeMark.getTradeId()); // 订单编号
            model.setTotalAmount(tradeMark.getAmount());// 商品价格
            request.setBizModel(model);
            request.setNotifyUrl(paymentParameter.getNotifyUrl());// 异步回调地址
            try {
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                return AliPrepaymentResponse.createResponse(tradeMark.getTradeId(), response.getBody());
            } catch (AlipayApiException e) {
                throw new CommentException("%s", e.getErrMsg());
            }
        } else {
            AlipayClient alipayClient = this.createPayClient(paymentParameter);
            AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();

            model.setProductCode("QUICK_WAP_WAY");
            model.setTimeoutExpress("15m");// 订单超时 m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）
            model.setSubject(tradeMark.getTitle()); // 商品名称
            model.setOutTradeNo(tradeMark.getTradeId()); // 订单编号
            model.setTotalAmount(tradeMark.getAmount());// 商品价格
            request.setBizModel(model);
            request.setNotifyUrl(paymentParameter.getNotifyUrl());// 异步回调地址
            request.setReturnUrl(paymentParameter.getReturnUrl());
            try {
                AlipayTradeWapPayResponse response = alipayClient.sdkExecute(request);
                return AliPrepaymentResponse.createResponse(tradeMark.getTradeId(), response.getBody());
            } catch (AlipayApiException e) {
                throw new CommentException("%s", e.getErrMsg());
            }
        }
    }


    @Override
    public void paymentFallback(FinishTradeHandler paymentHandler, Map<String, String> params) {
        PayResponse payResponse = PayResponse.createAliPayNotifyOkResponse(params);
        String tradeNo = payResponse.getOutTradeNo();

        if ("TRADE_CLOSED".equals(payResponse.getTradeState())) {// 交易已关闭
            paymentHandler.paymentFailure(TradeType.Ali, tradeNo, payResponse.getTransactionId(), payResponse.getFailCode(), payResponse.getFailMsg());
        } else if ("TRADE_SUCCESS".equals(payResponse.getTradeState())) {// 支付成功
            paymentHandler.paymentSuccessfully(TradeType.Ali, tradeNo, payResponse.getTransactionId());
        } else {// 其他
            log.info("AliPay perOrder tradeState：[{}]", payResponse.getTradeState());
        }
    }

    @Override
    public PayResponse close(String orderNo) {
        AlipayClient alipayClient = this.createPayClient(paymentParameter);
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        AlipayTradeCloseModel closeModel = new AlipayTradeCloseModel();
        closeModel.setOutTradeNo(orderNo);
        request.setBizModel(closeModel);
        try {
            AlipayTradeCloseResponse response = alipayClient.sdkExecute(request);
            return PayResponse.createAliCloseResponse(response);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void refund(FinishTradeHandler finishTradeHandler, String outTradeNo, String totalAmount, String refundAmount, String refundReason) {
        AlipayClient alipayClient = this.createPayClient(paymentParameter);
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel refundModel = new AlipayTradeRefundModel();
        refundModel.setOutTradeNo(outTradeNo);
        refundModel.setRefundAmount(refundAmount);// 退款金额
        refundModel.setRefundReason(refundReason);
        refundModel.setOutTradeNo(outTradeNo);// 用子订单ID作为标识
        request.setBizModel(refundModel);
        try {
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            PayResponse payResponse = PayResponse.createAliRefundResponse(response);
            if ("SUCCESS".equals(payResponse.getRefundStatus()) || "REFUNDED".equals(payResponse.getRefundStatus())) {
                finishTradeHandler.refundSuccessfully(TradeType.Ali, outTradeNo, payResponse.getTransactionId(), refundReason);
            } else {
                finishTradeHandler.refundFailure(TradeType.Ali, outTradeNo, payResponse.getTransactionId(), payResponse.getFailCode(), payResponse.getFailMsg());
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean analysisOfRefund(FinishTradeHandler paymentHandler, Map<String, String> params) {
        return false;
    }

    @Override
    public void selectPayment(FinishTradeHandler finishTradeHandler, String outTradeNo) {
        AlipayClient alipayClient = this.createPayClient(paymentParameter);
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); //创建API对应的request类
        AlipayTradeQueryModel queryModel = new AlipayTradeQueryModel();
        queryModel.setOutTradeNo(outTradeNo);
        request.setBizModel(queryModel);
        try {
            AlipayTradeQueryResponse response = alipayClient.execute(request); //通过alipayClient调用API，获得对应的response类
            PayResponse payResponse = PayResponse.createAliQueryResponse(response);

            if ("10000".equals(payResponse.getResultCode()) && "TRADE_SUCCESS".equals(payResponse.getTradeState())) {
                finishTradeHandler.paymentSuccessfully(TradeType.Ali, outTradeNo, payResponse.getTransactionId());
            } else {
                finishTradeHandler.paymentFailure(TradeType.Ali, outTradeNo, payResponse.getTransactionId(), payResponse.getFailCode(), payResponse.getFailMsg());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public PayResponse selectOfRefund(String outTradeNo, String operatorId) {

        AlipayClient alipayClient = this.createPayClient(paymentParameter);
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        AlipayTradeFastpayRefundQueryModel queryModel = new AlipayTradeFastpayRefundQueryModel();
        queryModel.setOutTradeNo(outTradeNo);
        queryModel.setOutRequestNo(operatorId);

        request.setBizModel(queryModel);
        try {
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request); //通过alipayClient调用API，获得对应的response类
            return PayResponse.createAliRefundQueryResponse(response);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public TradeType getTradeType() {
        return TradeType.Ali;
    }
}
